const axios = require('axios');
const cheerio = require('cheerio');
const config = require('./config');

// 代理获取器类
class ProxyFetcher {
  constructor() {
    this.proxyList = [];
    this.lastFetchTime = 0;
    this.fetchInterval = 5 * 60 * 1000; // 5分钟更新一次代理列表
  }

  async getProxy() {
    try {
      if (this.shouldFetchNewProxies()) {
        await this.updateProxyList();
      }
      
      if (this.proxyList.length === 0) {
        return null;
      }
      
      return this.proxyList[Math.floor(Math.random() * this.proxyList.length)];
    } catch (error) {
      console.error('获取代理失败:', error.message);
      return null;
    }
  }

  shouldFetchNewProxies() {
    return this.proxyList.length === 0 ||
      (Date.now() - this.lastFetchTime) > this.fetchInterval;
  }

  async updateProxyList() {
    try {
      const proxies = await this.fetchFromMultipleSources();
      if (proxies.length > 0) {
        console.log(`获取到 ${proxies.length} 个代理，开始验证可用性...`);
        
        // 并发验证代理
        const validationPromises = proxies.map(proxy => 
          this.validateProxy(proxy)
            .then(isValid => isValid ? proxy : null)
            .catch(() => null)
        );

        // 使用 Promise.all 并发验证，设置总体超时
        const validProxies = (await Promise.all(validationPromises))
          .filter(proxy => proxy !== null);

        this.proxyList = validProxies;
        this.lastFetchTime = Date.now();
        console.log(`验证完成，获取到 ${validProxies.length} 个可用代理`);
      }
    } catch (error) {
      console.error('更新代理列表失败:', error.message);
    }
  }

  async fetchFromMultipleSources() {
    const proxies = [];

    for (const url of config.PROXY_CONFIG.sources.proxyList.urls) {
      try {
        const response = await axios.get(url, {
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'
          },
          timeout: 10000
        });

        const $ = cheerio.load(response.data);
        let currentProxies = [];

        // 根据不同网站使用不同的解析逻辑
        if (url.includes('kuaidaili')) {
          $('table tbody tr').each((_, element) => {
            const ip = $(element).find('td[data-title="IP"]').text().trim();
            const port = $(element).find('td[data-title="PORT"]').text().trim();
            if (ip && port) {
              currentProxies.push(`http://${ip}:${port}`);
            }
          });
        } else if (url.includes('ip3366')) {
          $('table tbody tr').each((_, element) => {
            const ip = $(element).find('td:nth-child(1)').text().trim();
            const port = $(element).find('td:nth-child(2)').text().trim();
            if (ip && port) {
              currentProxies.push(`http://${ip}:${port}`);
            }
          });
        } else if (url.includes('89ip')) {
          $('table tbody tr').each((_, element) => {
            const ip = $(element).find('td:nth-child(1)').text().trim();
            const port = $(element).find('td:nth-child(2)').text().trim();
            if (ip && port) {
              currentProxies.push(`http://${ip}:${port}`);
            }
          });
        } else if (url.includes('66ip')) {
          $('table tbody tr').each((_, element) => {
            const ipPort = $(element).find('td:nth-child(1)').text().trim();
            if (ipPort && ipPort.includes(':')) {
              currentProxies.push(`http://${ipPort}`);
            }
          });
        }

        proxies.push(...currentProxies);
        console.log(`从 ${url} 获取到 ${currentProxies.length} 个代理`);

      } catch (error) {
        console.error(`从 ${url} 获取代理失败:`, error.message);
      }
    }

    return proxies;
  }

  async validateProxy(proxy) {
    try {
        const [host, port] = proxy.split('://')[1].split(':');
        const response = await axios.get('http://www.netbian.com', {
            proxy: {
                host,
                port,
                protocol: 'http'
            },
            headers: {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
                'Referer': 'http://www.netbian.com/'
            },
            timeout: 5000,
            maxRedirects: 5,
            validateStatus: function (status) {
                return status >= 200 && status < 300; // 只接受2xx状态码
            }
        }).catch(() => null); // 捕获所有错误并返回null

        return response && response.status === 200;
    } catch (error) {
        return false;
    }
  }
}

module.exports = new ProxyFetcher();